﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SharpAnalyzer.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;

namespace SharpAnalyzer.Analyzers
{
    internal abstract class ClassCouplingAnalyzerBase : CSharpSyntaxWalker
    {
        private readonly IDictionary<string, ITypeSymbol> types = new Dictionary<string, ITypeSymbol>();
        private readonly SemanticModel semanticModel;

        protected SemanticModel SemanticModel
        {
            get
            {
                return semanticModel;
            }
        }

        protected ClassCouplingAnalyzerBase(SemanticModel semanticModel)
          : base(SyntaxWalkerDepth.Node)
        {
            Verify.NotNull(() => semanticModel);

            this.semanticModel = semanticModel;
        }

        protected IEnumerable<string> GetCollectedTypesNames()
        {
            var source = types.Keys.ToList();
            return source.AsReadOnly();
        }

        protected void FilterType(TypeSyntax syntax)
        {
            if (syntax.Kind() == SyntaxKind.PredefinedType)
                return;
            SymbolInfo symbolInfo = SemanticModel.GetSymbolInfo(syntax);
            if (symbolInfo.Symbol == null || symbolInfo.Symbol.Kind != SymbolKind.NamedType)
                return;
            FilterTypeSymbol((ITypeSymbol)symbolInfo.Symbol);
        }

        protected void FilterTypeSymbol(ITypeSymbol symbol)
        {
            if (symbol == null)
                return;
            switch (symbol.TypeKind)
            {
                case TypeKind.Class:
                case TypeKind.Delegate:
                case TypeKind.Enum:
                case TypeKind.Interface:
                    string qualifiedName = TypeNameResolver.GetQualifiedName(symbol);
                    ITypeSymbol typeSymbol;
                    if (types.TryGetValue(qualifiedName, out typeSymbol))
                        break;
                    types[qualifiedName] = symbol;
                    break;
            }
        }
    }
}
